#pragma once

// Copyright (c) 2010 Manuel Peinado Gallego <manuel.peinado@gmail.com>
// Distributed under the MIT license

// MaterialManager.h : interface of the MaterialManager class
//

#include <set>
#include "Material.h"
#include "Common.h"
#include "MaterialEvent.h"



class MaterialManager
{
private:
    
    typedef std::set<ref<Material> > MaterialSet;

public:

    MaterialManager();

    // - - -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 

    void registerMaterial(ref<Material> mat);

    // - - -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
    
    // Deletes all materials
    void clear();

    // - - -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 

    // Return NULL ptr if material does not exist
    Material* getMaterialById(int id) const;
    Material* getMaterialByName(const std::wstring& name) const;
    Material* getDefaultMaterial() const;

    // - - -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 

    std::wstring generateNameFromPrefix(const std::wstring& prefix) const;
    
    // - - -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 

    typedef MaterialSet::const_iterator MaterialIt;
    MaterialIt beginMaterials() const;
    MaterialIt endMaterials() const;
    size_t getMaterialCount() const;

    // - - -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 

    // This will be called by the materials that are registered with this 
    // manager when one of their parameters change. The manager, in turn,
    // will notifiy all its listeners

    void notifyMaterialAppearanceChanged(MaterialEvent& event_);

private:

    MaterialSet m_materials;
    std::set<int> m_usedIds;

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
    // MaterialListeners stuff
public:

    void addMaterialListener(MaterialListener* listener);
    void removeMaterialListener(MaterialListener* listener);

private:

    // We use set<> to avoid duplicates
    typedef std::set<MaterialListener*>::iterator ListenerIt;
    std::set<MaterialListener *> m_listeners;
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
};

